package com.easyj.admin.edu.serviceimpl;

import java.util.List;
import java.util.Date;

import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.easyj.admin.edu.service.TrainingService;
import com.easyj.admin.activiti.service.TaskCommentService;
import com.easyj.admin.activiti.utils.ProcessUtils;
import com.easyj.admin.activiti.vo.SimpleApproveVO;
import com.easyj.admin.db.mapper.TrainingMapper;
import com.easyj.base.exception.*;
import com.easyj.base.security.SimpleUser;
import com.easyj.base.security.service.SecurityUtil;
import com.easyj.base.enums.Level2ApplyStatusEnum;
import com.easyj.base.common.page.Page;
import com.easyj.admin.db.model.TaskComment;
import com.easyj.admin.db.model.Training;
import com.easyj.admin.db.model.TrainingQO;

/**
 * 二级审批+驳回+抄送
 * @author hjf
 *
 */

@Service
public class TrainingServiceImpl implements TrainingService{

   
	@Autowired
	private  TrainingMapper trainingMapper;
	
	
	@Autowired
    private ProcessRuntime processRuntime;
	
	@Autowired
    private TaskRuntime taskRuntime;
	
	@Autowired
	private RuntimeService runtimeService;
	
	@Autowired
	private TaskService taskService;
	
	@Autowired
	private TaskCommentService taskCommentService;
	
	@Autowired
	private  HistoryService historyService;
	  	
	public Page<Training> findPage(TrainingQO filter){
	    Long total=trainingMapper.countByExample(filter);
		List<Training> rows=null;
		if(total>0l){
			filter.getPage().resetOffsetByTotal(total);
		    rows= trainingMapper.selectByExample(filter);
		}
		
		Page<Training> rtn=new Page<Training>(rows,total,filter.getPage());
		return rtn;
	}	
	
        
   	public List<Training> findList(TrainingQO filter){
        return trainingMapper.selectByExample(filter);
    }
	public long count(TrainingQO filter){
	     return trainingMapper.countByExample(filter);
	}	


	public Training findById(Long id){
		Training entity= trainingMapper.selectByPrimaryKey(id);
		return entity;
	}
	
	public List<TaskComment> findCommentsById(Long entityId){
		HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
		query.processInstanceBusinessKey(entityId.toString());
		query.processDefinitionKey(ProcessDefKey);
		HistoricProcessInstance processInstance =  query.singleResult();
		List<TaskComment> rtn=taskCommentService.findByProcInstId(processInstance.getId());
		return rtn;
	}
	
	
	
	@Transactional
	public int  apply(Training entity) throws EasyjException{
		entity.setApplyTime(new Date());
		SimpleUser usr=SecurityUtil.getOperator();
		entity.setApplicantId(usr.getId());
		entity.setDeptId(usr.getDepartmentId());
		entity.setStatus(Level2ApplyStatusEnum.WAITING.getKey());	
		entity.setApplyTime(new Date());
		int rtn= trainingMapper.insert(entity);
		
		//启动流程
		String businessKey = entity.getId().toString(); //业务key=entityId
		
		processRuntime.start(ProcessPayloadBuilder
	                        .start()
	                        .withProcessDefinitionKey(ProcessDefKey)
	                        .withName(entity.getApplyName())
	                        .withVariable("applicant", SecurityUtil.getOperatorId().toString()) //指定申请会务执行人为登录用户
	                        .withBusinessKey(businessKey)
	                        .build());
		
				
		
		return rtn;
	}
	
	/**
	 * 重新申请
	 * @param entity
	 * @return
	 * @throws EasyjException
	 */
	@Transactional(rollbackFor=Exception.class)
	public int  reApply(Training entity) throws EasyjException{
		Training find=trainingMapper.selectByPrimaryKey(entity.getId());
		if(find.getApplicantId().longValue()!=SecurityUtil.getOperatorId().longValue()) {
			throw new  ValidateException("非法操作！");
		}
		if(entity.getStatus().intValue()!=Level2ApplyStatusEnum.Repeat.getKey()){
			throw new  ValidateException("状态不是‘"+Level2ApplyStatusEnum.Repeat.getText()+"’！");
		}
		
		entity.setApplyTime(new Date());
		entity.setStatus(Level2ApplyStatusEnum.WAITING.getKey());
		int rtn= trainingMapper.updateByPrimaryKey(entity);
		
		//查找task
		org.activiti.engine.runtime.ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(find.getId().toString(), ProcessDefKey).active().singleResult();
		org.activiti.api.runtime.shared.query.Page<Task> pageTasks=taskRuntime.tasks(Pageable.of(0,1), TaskPayloadBuilder.tasks().withProcessInstanceId(processInstance.getId()).build());
		Task task=pageTasks.getContent().get(0);
		taskRuntime.complete(TaskPayloadBuilder.complete()
                .withTaskId(task.getId())
                .build());
		
		return rtn;
		
	}
	

	
	/**
	 * 审批不通过可修改再提交
	 */
	@Transactional(rollbackFor=Exception.class)
	public void approve(SimpleApproveVO approveVO) throws EasyjException{
		Task task=taskRuntime.task(approveVO.getTaskId());
		if(!task.getBusinessKey().equals(approveVO.getEntityId().toString())) {
			throw new  ValidateException("数据不符合要求！");
		}
		Training entity=trainingMapper.selectByPrimaryKey(approveVO.getEntityId());
		if(entity.getStatus().intValue()!=Level2ApplyStatusEnum.WAITING.getKey()){
			throw new  ValidateException("状态不是‘等待审批’");
		}					
		
		//update entity
		if(approveVO.isPassed()){
		    entity.setStatus(Level2ApplyStatusEnum.WaitAudit.getKey());
	    }else {
	    	entity.setStatus(Level2ApplyStatusEnum.Repeat.getKey());
	    }
		
		entity.setApproveComment(approveVO.getComment());
		entity.setApproveId(approveVO.getApproveUserId());
		entity.setApproveTime(new Date());		
		trainingMapper.updateByPrimaryKeySelective(entity);
		
		//加上审批意见
		ProcessUtils.addComment(task,SecurityUtil.getOperatorId().toString(), approveVO.isPassed(), approveVO.getComment());		
         //流程定义 指定了 assginee 不需要 claim
		if(StringUtils.isBlank(task.getAssignee())){
			taskRuntime.claim(
               TaskPayloadBuilder.claim().withTaskId(approveVO.getTaskId()).build());
		}
		
	     //用原来的taskService	
		taskService.setVariable(approveVO.getTaskId(), "pass", approveVO.isPassed());
		taskService.complete(approveVO.getTaskId());
		
		/**
		 * 接口taskRuntime.complete() 还真的臭，.withVariable 只能是local variable,使用网关方式判定退回，会报错。
		taskRuntime.complete(
                TaskPayloadBuilder.complete()
                        .withTaskId(approveVO.getTaskId())
                        .withVariable("pass", approveVO.isPassed())
                        .build());  
		*/
		//抄送
		if(approveVO.getNotifyUsers()!=null) {
			for(String uId:approveVO.getNotifyUsers()) {
				ProcessUtils.createNotifyTask(approveVO.getTaskId(), uId);
			}
		}
		
	}
	
	@Transactional(rollbackFor=Exception.class)
	public void auditApply(SimpleApproveVO approveVO) throws EasyjException{
		Task task=taskRuntime.task(approveVO.getTaskId());
		if(!task.getBusinessKey().equals(approveVO.getEntityId().toString())) {
			throw new  ValidateException("数据不符合要求！");
		}
		Training entity=trainingMapper.selectByPrimaryKey(approveVO.getEntityId());
		if(entity.getStatus().intValue()!=Level2ApplyStatusEnum.WaitAudit.getKey()){
			throw new  ValidateException("状态不是‘"+Level2ApplyStatusEnum.WaitAudit.getText()+"’！");
		}
					
		
		//update entity
		if(approveVO.isPassed()){
		    entity.setStatus(Level2ApplyStatusEnum.PASSED.getKey());
	    }else {
	    	entity.setStatus(Level2ApplyStatusEnum.REJECT.getKey());
	    }
		
		entity.setApproveComment(approveVO.getComment());
		entity.setApproveId(approveVO.getApproveUserId());
		entity.setApproveTime(new Date());		
		trainingMapper.updateByPrimaryKeySelective(entity);
		
		//加上审批意见
		ProcessUtils.addComment(task,SecurityUtil.getOperatorId().toString(), approveVO.isPassed(), approveVO.getComment());		
		if(StringUtils.isBlank(task.getAssignee())){
			taskRuntime.claim(
               TaskPayloadBuilder.claim().withTaskId(approveVO.getTaskId()).build());
		}
		taskRuntime.complete(
                TaskPayloadBuilder.complete()
                        .withTaskId(approveVO.getTaskId()) 
                        .build()); 
		
		//抄送
		if(approveVO.getNotifyUsers()!=null) {
			for(String uId:approveVO.getNotifyUsers()) {
				ProcessUtils.createNotifyTask(approveVO.getTaskId(), uId);
			}
		}
				
	}
	
	
	
	@Transactional
	public int  updateEntity(Training entity) throws EasyjException{
		//只可修改自已
	    Training find=trainingMapper.selectByPrimaryKey(entity.getId());
		if(find.getApplicantId().longValue()!=SecurityUtil.getOperatorId().longValue()) {
			throw new  ValidateException("非法操作！");
		}
		if(entity.getStatus().intValue()!=Level2ApplyStatusEnum.WAITING.getKey()){
			throw new  ValidateException("非法操作,状态不是‘等待审批’");
		}
		
		entity.setStatus(find.getStatus());
		entity.setApproveTime(find.getApproveTime());
		int rtn= trainingMapper.updateByPrimaryKey(entity);
		return rtn;
	}
	
	/**
     * 按实体ID取消流程
	 */
	@Transactional(rollbackFor=Exception.class)
	public int  cancel(Long id) throws EasyjException{
		Training find=trainingMapper.selectByPrimaryKey(id);
		if(find.getApplicantId().longValue()!=SecurityUtil.getOperatorId().longValue()) {
			throw new  ValidateException("非法操作！");
		}
		if(!(find.getStatus().intValue()==Level2ApplyStatusEnum.WAITING.getKey()
				||find.getStatus().intValue()==Level2ApplyStatusEnum.Repeat.getKey())){
			throw new  ValidateException("非法操作,状态不是‘等待审批’或‘"+Level2ApplyStatusEnum.Repeat.getText()+"’！");
		}
		
		find.setStatus(Level2ApplyStatusEnum.CANCEl.getKey());
		find.setApproveTime(new Date()); //共用
		
		int rtn= trainingMapper.updateByPrimaryKey(find);
		
		
		//取消,delete流程实例 
		org.activiti.engine.runtime.ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(find.getId().toString(), ProcessDefKey).active().singleResult();
		runtimeService.deleteProcessInstance(processInstance.getId(), "申请人取消");
		
		return rtn;
	}
	
 

}
